#ifndef __PARSER_H
#define __PARSER_H 1

#include <lexer.h>
#include <ast.h>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <any>
#include <scope.h>

class Parser {
private:
    Lexer& _lexer;
    int _inLoop;
    int _incase;
    int _nested;
    std::unordered_map<std::string, int> _enum;
    std::unordered_map<std::string, Type> _typeAlias;
    std::unordered_map<std::string, Type> _func;

    std::unordered_set<std::string> _vars;
    std::vector<std::pair<Type, std::string>> _locals;

    std::unordered_map<std::string, Type> _struct;


    bool statWritable(Stat stat);


public:
    Parser(Lexer& lexer) : _lexer(lexer),  _nested(0) {
    }

    // FIXME
    bool isVariable(Stat stat) {
        return stat.type() == typeid(VarStat) && _vars.count(std::any_cast<VarStat>(stat).name);
    }
    bool isFunction(Stat stat) {
        return stat.type() == typeid(NameStat); //  && _func.count(std::any_cast<NameStat>(stat).name) > 0;
    }

    Stat parse();
    Stat parseStat();

    Stat parseBlockStat();
    Stat parseForStat();
    Stat parseWhileStat();
    Stat parseDoWhileStat();
    Stat parseIfStat();
    Stat parseFuncDefStat();

    Stat parseSwitchCaseBlockStat();
    Stat parseSwitchStat();
    Stat parseCaseStat();

    Stat parseStructStat();
    Stat parseEnumStat();
    Stat parseUnionStat();

    Stat parseBreakStat();
    Stat parseContinueStat();

    Stat parseTypedefStat();

    Stat parseGotoStat();

    Stat parseReturnStat();




    Stat parseEmptyStat();

    Stat parseExprStat(TokenType ter1 = kTokenSemi, TokenType ter2 = kTokenSemi);

    Stat parsePrimaryStat();


    std::pair<Type, std::string> parseDeclarationSpec();

    Stat parseParamStat();
    Stat parseFunctionStat(Type type, std::string name);

    Stat parseVariableDefineStat(Type type, std::string name, bool isStatic);
};


#endif //__PARSER_H
